﻿#region Using directives
using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.IO;
using System.Xml;
using System.Windows.Forms;
using System.Drawing;
using System.Collections;
#endregion

namespace gpsMe.Utils
{
    /// <summary>
    /// Usefull functions
    /// </summary>
    public static class gpsMeUtils
    {
        #region Application directory
        /// <summary>
        /// Returns the path of the application .exe
        /// </summary>
        /// <returns>path in a string</returns>
        public static string ApplicationDirectory
        {
            get
            {
                return Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase).Replace(@"file:\", "");
            }
        }
        #endregion

        #region Current hour
        /// <summary>
        /// Returns the current hour in a string format
        /// "hh:mm"
        /// </summary>
        public static string CurrentHour
        {
            get
            {
                string r_sCurrentHour = "";
                if (DateTime.Now.Hour.ToString().Length < 2)
                    r_sCurrentHour += "0" + DateTime.Now.Hour.ToString();
                else
                    r_sCurrentHour += DateTime.Now.Hour.ToString();
                if (DateTime.Now.Minute.ToString().Length < 2)
                    r_sCurrentHour += ":0" + DateTime.Now.Minute.ToString();
                else
                    r_sCurrentHour += ":" + DateTime.Now.Minute.ToString();
                return r_sCurrentHour;
            }
        }
        #endregion

        #region XML loading
        /// <summary>
        /// Loads the value of a node
        /// </summary>
        /// <param name="p_oXmlTextReader">XmlTextReader instanciation</param>
        /// <returns>string of the value</returns>
        public static string LoadValueFromXml(ref XmlTextReader p_oXmlTextReader)
        {
            string r_sValue = "";
            p_oXmlTextReader.Read();
            if (p_oXmlTextReader.HasValue)
                r_sValue = p_oXmlTextReader.Value;
            p_oXmlTextReader.Read();
            return r_sValue;
        }

        /// <summary>
        /// Loads the integer value of a node
        /// </summary>
        /// <param name="p_oXmlTextReader">XmlTextReader instanciation</param>
        /// <returns>integer value</returns>
        public static int LoadIntegerValueFromXml(ref XmlTextReader p_oXmlTextReader)
        {
            return int.Parse(gpsMeUtils.LoadValueFromXml(ref p_oXmlTextReader));
        }

        /// <summary>
        /// Loads the boolean value of a node
        /// </summary>
        /// <param name="p_oXmlTextReader">XmlTextReader instanciation</param>
        /// <returns>boolean value</returns>
        public static bool LoadBooleanValueFromXml(ref XmlTextReader p_oXmlTextReader)
        {
            return bool.Parse(gpsMeUtils.LoadValueFromXml(ref p_oXmlTextReader));
        }

        /// <summary>
        /// Loads the double value of a node
        /// </summary>
        /// <param name="p_oXmlTextReader">XmlTextReader instanciation</param>
        /// <returns>double value</returns>
        public static double LoadDoubleValueFromXml(ref XmlTextReader p_oXmlTextReader)
        {
            string sValueString = gpsMeUtils.LoadValueFromXml(ref p_oXmlTextReader);
            try
            {
                return Double.Parse(sValueString);
            }
            catch
            {
                try
                {
                    return Double.Parse(sValueString.Replace('.', ','));
                }
                catch
                {
                    try
                    {
                        return Double.Parse(sValueString.Replace(',', '.'));
                    }
                    catch
                    {
                        return Double.NaN;
                    }
                }
            }
        }
        #endregion

        #region Memory management
        /// <summary>
        /// malloc style ^^
        /// </summary>
        /// <param name="byteCount">int byteCount</param>
        /// <returns>pointer of the allocated memory space</returns>
        public static IntPtr LocalAlloc(int p_iByteCount)
        {
            IntPtr ptr = Win32.LocalAlloc(Win32.LMEM_ZEROINIT, p_iByteCount);
            if (ptr == IntPtr.Zero)
            {
                throw new OutOfMemoryException();
            }

            return ptr;
        }

        /// <summary>
        /// Free the memory by pointer
        /// </summary>
        /// <param name="hMem">pointer to the memory space thet needs to be free</param>
        public static void LocalFree(IntPtr oHMem)
        {
            IntPtr ptr = Win32.LocalFree(oHMem);
            if (ptr != IntPtr.Zero)
            {
                throw new ArgumentException();
            }
        }
        #endregion

        #region File system
        /// <summary>
        /// Loads all the contents of a folder in a treenode
        /// </summary>
        /// <param name="_strPath">path of the directory to list</param>
        /// <param name="_Node">treenode to affect</param>
        public static void AddDirectoryContentToTreeNode(string p_sPath, TreeNode p_oTreeNode)
        {
            DirectoryInfo Parent = new DirectoryInfo(p_sPath);
            // Parse files
            foreach (FileInfo NextFile in Parent.GetFiles())
            {
                p_oTreeNode.Nodes.Add(NextFile.Name);
            }
            // Parse directories
            foreach (DirectoryInfo NextFolder in Parent.GetDirectories())
            {
                TreeNode oDirectoryNode = p_oTreeNode.Nodes.Add(NextFolder.Name);
                // Set color, icons...
                oDirectoryNode.ForeColor = Color.Blue;
                // Recurse
                AddDirectoryContentToTreeNode(NextFolder.FullName, oDirectoryNode);
            }
        }

        /// <summary>
        /// Loads all the contents of a folder in a treenode
        /// </summary>
        /// <param name="_strPath">path of the directory to list</param>
        /// <param name="_Node">treenode to affect</param>
        public static void AddDirectorySpecificContentToTreeNode(string p_sPath, TreeNode p_oTreeNode, string p_sExtension)
        {
            DirectoryInfo Parent = new DirectoryInfo(p_sPath);
            // Parse files
            foreach (FileInfo NextFile in Parent.GetFiles())
            {
                if (NextFile.Name.EndsWith(p_sExtension, StringComparison.OrdinalIgnoreCase))
                    p_oTreeNode.Nodes.Add(NextFile.Name);
            }
            // Parse directories
            foreach (DirectoryInfo NextFolder in Parent.GetDirectories())
            {
                TreeNode oDirectoryNode = p_oTreeNode.Nodes.Add(NextFolder.Name);
                // Set color, icons...
                oDirectoryNode.ForeColor = Color.Blue;
                // Recurse
                AddDirectorySpecificContentToTreeNode(NextFolder.FullName, oDirectoryNode, p_sExtension);
            }
        }

        /// <summary>
        /// Find every files in the file system whose extensions is the same that the one given in params
        /// </summary>
        /// <param name="p_sPath">path from where to lookup</param>
        /// <param name="p_oTreeNode">used for recursivity, put new TreeNode() in it</param>
        /// <param name="p_sExtension">extension of the files to find</param>
        /// <param name="p_oFilesList">also used for recursivity, put new ArrayList() in it</param>
        /// <returns>ArrayList of all the files that were found</returns>
        public static ArrayList FindAllFilesFromExtension(string p_sPath, TreeNode p_oTreeNode, string p_sExtension, ArrayList p_oFilesList)
        {
            DirectoryInfo Parent = new DirectoryInfo(p_sPath);
            // Parse files
            foreach (FileInfo NextFile in Parent.GetFiles())
            {
                if (NextFile.Name.EndsWith(p_sExtension, StringComparison.OrdinalIgnoreCase))
                    p_oFilesList.Add(Parent.FullName + @"\" + NextFile.Name);
            }
            // Parse directories
            foreach (DirectoryInfo NextFolder in Parent.GetDirectories())
            {
                TreeNode oDirectoryNode = p_oTreeNode.Nodes.Add(NextFolder.Name);
                // Set color, icons...
                oDirectoryNode.ForeColor = Color.Blue;
                // Recurse
                FindAllFilesFromExtension(NextFolder.FullName, oDirectoryNode, p_sExtension, p_oFilesList);
            }
            return p_oFilesList;
        }

        /// <summary>
        /// Returns the file name without his extension
        /// </summary>
        /// <param name="p_sPath">file path</param>
        /// <returns>file name</returns>
        public static string FileNameFromPath(string p_sPath)
        {
            return Path.GetFileNameWithoutExtension(p_sPath);
        }

        /// <summary>
        /// Returns the path of the directory that contains the file given in parameters
        /// </summary>
        /// <param name="p_sPath"></param>
        /// <returns></returns>
        public static string FolderPathFromFilePath(string p_sPath)
        {
            return new FileInfo(p_sPath).Directory.FullName;
        }
        #endregion

        #region MethodInvoker delegate
        /// <summary>
        /// Delegate that allows code to ensure that any updates to the form occurs to the form's own thread
        /// </summary>
        public delegate void MethodInvoker();
        #endregion
    }
}
